#include<bits/stdc++.h>
using namespace std;
 
const int INF=INT_MAX;
int n,m;
int weight[5005][5005];//用于记录所有边的关系
int lowcost[5005];//用于记录距离树的距离最短路程
 
void Prim()
{
    int i,j,sum=0,minn,minIndex;

    //初始化最小花费数组，默认先把离1点最近的找出来放好
    for(i=1;i<=n;i++)
        lowcost[i] = weight[1][i];

    lowcost[1]=0;   //记录1已经被访问过了，所以lowcost变为0

    //1已经访问过了，所以循环n-1次
    for(i=1; i<n; i++)
    {
        minn=INF;

        for(j=1;j<=n;j++)
        {
            //该节点没有被访问过且代价小于minn
            if(lowcost[j] && lowcost[j]<minn)
            {
                minn=lowcost[j];    //对于最小值赋值
                minIndex=j;         //对于最小值的下标赋值
            }
        }

        lowcost[minIndex]=0;    //记录这个点已经被访问过了
        sum+=minn;

        // 如果这点没有被访问过，而且这个点到任意一点的距离
        // 比现在到树的距离近，那么更新
        for(j=1;j<=n;j++)
        {
            if(weight[minIndex][j]<lowcost[j])
                lowcost[j]=weight[minIndex][j];
        }
    }

    //检测如果有lowcost的值不为0，则说明该图不是连通图
    for(i=1;i<=n;i++)
    {
        if(lowcost[i]!=0)
        {
            cout << "orz" << endl;
            return;
        }
    }

    // 输出最小生成树的权值
    cout << sum << endl;
}
 
int main()
{
    // n个节点、m条边
    cin >> n >> m;

    //初始化maps，均为INF。访问过之后变为0
    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
             weight[i][j]=INF;
    }

    //无向图，对称
    int u, v, w;
    for(int i=1;i<=m;i++)
    {
        // 输入边和权值(u, v) w
        cin >> u >> v >> w;

        // 记录每条边的权值
        if(w < weight[u][v])
            weight[v][u] = weight[u][v] = w;
    }

    Prim();

    return 0;
}